#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
#include <signal.h>
#include <sys/wait.h>


#define BUF_SIZE 100

void error_handling(char *buf);
void read_childproc(int sig);


int main(int argc, char *argv[]){

	int serv_sock,clnt_sock;
	struct sockaddr_in serv_adr,clnt_adr;

	pid_t pid;
	struct sigaction act;
	socklen_t adr_sz;
	int str_len, state;
	char buf[BUF_SIZE];

	if (argc!=2)
	{
		printf("usage error\n");
		exit(1);
	}
	act.sa_handler=read_childproc;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	state=sigaction(SIGCHLD,&act,0);
	serv_sock=socket(PF_INET,SOCK_STREAM,0);
	memset(&serv_adr,0,sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));

	if(bind(serv_sock,(struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
		error_handling("bind error");

	if (listen(serv_sock,5)==-1)
	{
		error_handling("listen error");
	}
	while(1){
	
		adr_sz = sizeof(clnt_adr);
		clnt_sock =accept(serv_sock,(struct sockaddr*)&clnt_adr, &adr_sz);
		if (clnt_sock==-1)
		{
			continue;
		}
		else
			puts("new client connected...");

		pid =fork();
		if (pid==-1)
		{
			close(clnt_sock);
			continue;
		}
		if(pid ==0){
			close(serv_sock);
			while((str_len =read(clnt_sock,buf,BUF_SIZE))!=0)
				write(clnt_sock,buf,str_len);
			close(clnt_sock);
			puts("client disconnected...");
			return 0;
		}else
			close(clnt_sock);
	}
	close(serv_sock);
	return 0;
}

void read_childproc(int sig){

	pid_t pid;
	int status ;
	pid =waitpid(-1,&status,WNOHANG);
	printf("removed proc id: %d\n",pid);
}

void error_handling(char* buf){
	fputs(buf, stderr);
	fputs('\n', stderr);
	exit(1);
}